package com.zh.media.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zh.common.exception.BusinessException;
import com.zh.common.utils.RedisUtil;
import com.zh.media.domain.dto.UpdateWorkInfoDto;
import com.zh.media.mapper.WorkInfoMapper;
import com.zh.media.service.WorkInfoService;
import com.zh.web.domain.media.entity.WorkInfo;
import com.zh.web.enums.State;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;
import java.util.Set;

import static com.zh.media.config.RedisKeyConfig.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zh
 * @since 2024-10-02
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class WorkInfoServiceImpl extends ServiceImpl<WorkInfoMapper, WorkInfo> implements WorkInfoService {

    private final WorkInfoMapper workInfoMapper;
    private final RedisUtil redisUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String praise(UpdateWorkInfoDto updateWorkInfoDto) {
        Long worksId = updateWorkInfoDto.getWorksId();
        Long userId = updateWorkInfoDto.getUserId();
        State praise = updateWorkInfoDto.getPraise();

        WorkInfo workInfo = workInfoMapper.getByArticleIdAndUserId(worksId, userId);
        if (workInfo == null) {
            // 未点赞，新增点赞记录
            WorkInfo newWorkInfo = new WorkInfo();
            newWorkInfo.setWorksId(worksId);
            newWorkInfo.setUserId(userId);
            newWorkInfo.setPraise(praise);
            workInfoMapper.insert(newWorkInfo);
        } else {
            // 已存在点赞记录，更新
            WorkInfo updateWorkInfo = new WorkInfo();
            updateWorkInfo.setId(workInfo.getId());
            updateWorkInfo.setPraise(praise);
            workInfoMapper.updateWorkInfo(updateWorkInfo);
        }
        // 重新获取更新后的记录
        WorkInfo updatedWorkInfo = workInfoMapper.getByArticleIdAndUserId(worksId, userId);
        if (updatedWorkInfo == null) {
            if (praise == State.CONFIRM) {
                throw new BusinessException("点赞失败");
            } else if (praise == State.CANCEL) {
                throw new BusinessException("取消点赞失败");
            }
            return "操作失败";
        }
        // 处理 Redis 缓存
        String key = PRISE_SET_KEY_PREFIX + worksId;
        Set<String> priseSet = redisUtil.getSet(key);
        if (CollUtil.isEmpty(priseSet)) {
            synchronized (this) {
                priseSet = redisUtil.getSet(key); // 再次检查，避免多线程问题
                if (CollUtil.isEmpty(priseSet)) {
                    priseSet = workInfoMapper.getPriseSet(worksId);
                    if (CollUtil.isNotEmpty(priseSet)) {
                        redisUtil.addSet(key, priseSet.toArray(new String[0]));
                    }
                }
            }
        }
        if (praise == State.CONFIRM) {
            redisUtil.addSet(key, String.valueOf(userId));
            return "点赞成功";
        } else if (praise == State.CANCEL) {
            redisUtil.removeSet(key, String.valueOf(userId));
            return "取消点赞成功";
        }
        return "操作失败";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String collect(UpdateWorkInfoDto updateWorkInfoDto) {
        Long worksId = updateWorkInfoDto.getWorksId();
        Long userId = updateWorkInfoDto.getUserId();
        State collect = updateWorkInfoDto.getCollect();

        WorkInfo workInfo = workInfoMapper.getByArticleIdAndUserId(worksId, userId);
        if (workInfo == null) {
            // 未收藏，新增收藏记录
            WorkInfo newWorkInfo = new WorkInfo();
            newWorkInfo.setWorksId(worksId);
            newWorkInfo.setUserId(userId);
            newWorkInfo.setCollect(collect);
            workInfoMapper.insert(newWorkInfo);
        } else {
            // 已存在收藏记录，更新
            WorkInfo updateWorkInfo = new WorkInfo();
            updateWorkInfo.setId(workInfo.getId());
            updateWorkInfo.setCollect(collect);
            workInfoMapper.updateWorkInfo(updateWorkInfo);
        }

        // 重新获取更新后的记录
        WorkInfo updatedWorkInfo = workInfoMapper.getByArticleIdAndUserId(worksId, userId);
        if (updatedWorkInfo == null) {
            if (collect == State.CONFIRM) {
                throw new BusinessException("收藏失败");
            } else if (collect == State.CANCEL) {
                throw new BusinessException("取消收藏失败");
            }
            return "操作失败";
        }

        // 处理 Redis 缓存
        String key = COLLECT_SET_KEY_PREFIX + worksId;
        Set<String> collectSet = redisUtil.getSet(key);
        if (CollUtil.isEmpty(collectSet)) {
            synchronized (this) {
                collectSet = redisUtil.getSet(key); // 再次检查，避免多线程问题
                if (CollUtil.isEmpty(collectSet)) {
                    collectSet = workInfoMapper.getCollectSet(worksId);
                    if (CollUtil.isNotEmpty(collectSet)) {
                        redisUtil.addSet(key, collectSet.toArray(new String[0]));
                    }
                }
            }
        }

        if (collect == State.CONFIRM) {
            redisUtil.addSet(key, String.valueOf(userId));
            return "收藏成功";
        } else {
            redisUtil.removeSet(key, String.valueOf(userId));
            return "取消收藏成功";
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateView(UpdateWorkInfoDto updateWorkInfoDto) {
        Long worksId = updateWorkInfoDto.getWorksId();
        Long userId = updateWorkInfoDto.getUserId();
        Integer viewCount = updateWorkInfoDto.getViewCount();
        WorkInfo workInfo = workInfoMapper.getByArticleIdAndUserId(worksId, userId);
        boolean success;
        if (workInfo == null) {
            //1.未浏览记录,新增浏览记录
            WorkInfo newWorkInfo = new WorkInfo();
            newWorkInfo.setWorksId(worksId);
            newWorkInfo.setUserId(userId);
            newWorkInfo.setViewCount(viewCount);
            workInfoMapper.insert(newWorkInfo);
        } else {
            //2.已存在浏览记录 更新
            WorkInfo updateWorkInfo = new WorkInfo();
            updateWorkInfo.setId(workInfo.getId());
            updateWorkInfo.setViewCount(workInfo.getViewCount() + viewCount);
            workInfoMapper.updateWorkInfo(updateWorkInfo);
        }
        WorkInfo updatedWorkInfo = workInfoMapper.getByArticleIdAndUserId(worksId, userId);
        success = null != updatedWorkInfo;
        if (success) {
            Integer nowViewCount = redisUtil.get(VIEW_COUNT_KEY_PREFIX + worksId);
            if (null == nowViewCount) {
                synchronized (this) {
                    //3.重建浏览缓存
                    redisUtil.set(VIEW_COUNT_KEY_PREFIX + worksId, updatedWorkInfo.getViewCount());
                }
            }
            log.info("浏览量更新成功");
        } else {
            throw new BusinessException("浏览量更新失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateShare(UpdateWorkInfoDto updateWorkInfoDto) {
        Long worksId = updateWorkInfoDto.getWorksId();
        Long userId = updateWorkInfoDto.getUserId();
        Integer shareCount = updateWorkInfoDto.getShareCount();
        WorkInfo workInfo = workInfoMapper.getByArticleIdAndUserId(worksId, userId);
        boolean success;
        if (workInfo == null) {
            //1.未分享记录,新增分享记录
            WorkInfo newWorkInfo = new WorkInfo();
            newWorkInfo.setWorksId(worksId);
            newWorkInfo.setUserId(userId);
            newWorkInfo.setShareCount(shareCount);
            workInfoMapper.insert(newWorkInfo);
        } else {
            //2.已存在分享记录 更新
            WorkInfo updateWorkInfo = new WorkInfo();
            updateWorkInfo.setId(workInfo.getId());
            updateWorkInfo.setShareCount(workInfo.getShareCount() + shareCount);
            workInfoMapper.updateWorkInfo(updateWorkInfo);
        }
        WorkInfo updatedWorkInfo = workInfoMapper.getByArticleIdAndUserId(worksId, userId);
        success = null != updatedWorkInfo;
        if (success) {
            Integer nowShareCount = redisUtil.get(SHARE_COUNT_KEY_PREFIX + worksId);
            if (null == nowShareCount) {
                synchronized (this) {
                    //3.重建分享缓存
                    redisUtil.set(SHARE_COUNT_KEY_PREFIX + worksId, updatedWorkInfo.getShareCount());
                }
            }
            log.info("分享量更新成功");
        } else {
            throw new BusinessException("分享量更新失败");
        }
    }

    @Override
    public Integer countPraise(Long id) {
        Long praiseCount = redisUtil.getSetSize(PRISE_SET_KEY_PREFIX + id);
        if (praiseCount != null) {
            return praiseCount.intValue();
        }
        return workInfoMapper.selectPraiseCount(id);
    }

    @Override
    public Integer countCollect(Long id) {
        Long collectCount = redisUtil.getSetSize(COLLECT_SET_KEY_PREFIX + id);
        if (collectCount != null) {
            return collectCount.intValue();
        }
        return workInfoMapper.selectCollectCount(id);
    }

    @Override
    public Integer countView(Long id) {
        Integer view = redisUtil.get(VIEW_COUNT_KEY_PREFIX + id);
        if (view != null) {
            return view;
        }
        return workInfoMapper.selectViewCount(id);
    }

    @Override
    public Integer countShare(Long id) {
        Integer share = redisUtil.get(SHARE_COUNT_KEY_PREFIX + id);
        if (share != null) {
            return share;
        }
        return workInfoMapper.selectShareCount(id);
    }

    @Override
    public WorkInfo selectByIdAndUserId(Long id, Long userId) {
        WorkInfo  workInfo= workInfoMapper.selectByIdAndUserId(id, userId);
        return null;
    }
}
